﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Reflection;


namespace MinConsole.Gaf.Dh
{


    /// <summary>
    /// This class models a storage structure for objects queriable by id or property name and property value
    /// </summary>
    public class ObjectPool
    {

        #region FieldsAndProps


        #region TotalCount
        /// <summary>
        /// the total number of items in the Object pool 
        /// </summary>
        private int _TotalCount;
        public int TotalCount
        {
            get
            {
                return _TotalCount;
            }
        }

        #endregion  TotalCount


        public int ID { get; set; }

        /// <summary>
        /// The actual storage data structure 
        /// </summary>
        private Dictionary<Type, Dictionary<Int32, Object>> m_pool;

        #endregion Props

        #region Constructors

        public ObjectPool()
        {
            m_pool = new Dictionary<Type, Dictionary<Int32, Object>>();
        }

        public System.Collections.Specialized.ListDictionary LidMetaName { get; set; }



        #endregion Constructors

        #region UtilityMethods

        /// <summary>
        /// adds an item to the data structure 
        /// </summary>
        /// <typeparam name="T">the type of the item </typeparam>
        /// <param name="pID"> the item's id</param>
        /// <param name="value"> the actual value of the item </param>
        public void AddItem<T>(Int32 pID, T value)
        {
            Type myType = typeof(T);

            if (!m_pool.ContainsKey(myType))
            {
                m_pool.Add(myType, new Dictionary<int, object>());
                m_pool[myType].Add(pID, value);

                _TotalCount++;
                return;
            }

            if (!m_pool[myType].ContainsKey(pID))
            {
                m_pool[myType].Add(pID, value);
                _TotalCount++;
                return;
            }

            m_pool[myType][pID] = value;
            _TotalCount++;
            //Utils.Debugger.WriteIf("Adding 1 to pool count , pool count is " + this._TotalCount);
        }

        /// <summary>
        /// Adds an item to the last position of the data structure 
        /// </summary>
        /// <typeparam name="T">the type of the item </typeparam>
        /// <param name="value">the actual object to add </param>
        public void AddItem<T>(T value)
        {
            Int32 pID = _TotalCount;
            Type myType = typeof(T);

            if (!m_pool.ContainsKey(myType))
            {
                m_pool.Add(myType, new Dictionary<int, object>());
                m_pool[myType].Add(pID, value);

                _TotalCount++;
                return;
            }

            if (!m_pool[myType].ContainsKey(pID))
            {
                m_pool[myType].Add(pID, value);
                _TotalCount++;
                return;
            }

            m_pool[myType][pID] = value;
            _TotalCount++;
            //Utils.Debugger.WriteIf("Adding 1 to pool count , pool count is " + this._TotalCount);
        }

        /// <summary>
        /// removes an item by its id
        /// </summary>
        /// <typeparam name="T">the type of the item </typeparam>
        /// <param name="pID"></param>
        /// <returns></returns>
        public bool RemoveItem<T>(Int32 pID)
        {
            Type myType = typeof(T);

            if (!m_pool.ContainsKey(myType))
                return false;

            if (!m_pool[myType].ContainsKey(pID))
                return false;

            _TotalCount--;
            return m_pool[myType].Remove(pID);
        }

        /// <summary>
        /// checks wether or not the pool contains an item by its id and type
        /// </summary>
        /// <typeparam name="T">the type of the item</typeparam>
        /// <param name="pID">its id</param>
        /// <returns>bool whether of not the item exists </returns>
        public bool ContainsKey<T>(Int32 pID)
        {
            Type myType = typeof(T);

            if (!m_pool.ContainsKey(myType))
                return false;

            if (!m_pool[myType].ContainsKey(pID))
                return false;

            return m_pool[myType].ContainsKey(pID);
        }

        /// <summary>
        /// Gets an IEnumerable collections of objects with Type T
        /// </summary>
        /// <typeparam name="T">The type of the items</typeparam>
        /// <returns>the dictionary of objects</returns>
        public IEnumerable<T> GetItems<T>()
        {
            Type myType = typeof(T);

            if (!m_pool.ContainsKey(myType))
                return new T[0];

            return m_pool[myType].Values as IEnumerable<T>;
        }

        /// <summary>
        /// Gets the item.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pID">The p ID.</param>
        /// <returns></returns>
        /// <exception cref="KeyNotFoundException"></exception>
        public T GetItem<T>(Int32 pID)
        {
            // will throw KeyNotFoundException if either of the dictionaries 
            // does not hold the required key
            return (T)m_pool[typeof(T)][pID];
        }

        #endregion UtilityMethods

        #region MethodsInDev

        /// <summary>
        /// Returns the first Item from        the Collection by it's property name and its value
        /// works only on the first level 
        /// </summary>
        /// <typeparam name="T">The Type of the Object to get </typeparam>
        /// <param name="strPropMetaName"> the string representation of the </param>
        /// <param name="strPropValue">the value of the property</param>
        /// <returns></returns>
        //public T GetItemByPropertyValue<T>(String strPropMetaName, String strPropValue)
        //{
        //  //old configure the logger
        //  logger.Debug("METHOD START --- GetItemByPropertyValue");


        //  Type myType = typeof(T);


        //  for (int i = 0; i < this.TotalCount; i++)
        //  {
        //    if (!m_pool.ContainsKey(myType))
        //    {
        //      return default(T);
        //    }
        //    else
        //    {

        //        if (!m_pool[myType].ContainsKey(i))
        //            continue ; 


        //        //get an item object having the same type
        //        T item = (T)m_pool[typeof(T)][i];
        //        if (this.SearchPropByValue(item, strPropMetaName, strPropValue))
        //          return item;
        //        else
        //          continue;

        //    } //eof else 
        //  }//eof for 
        //  return default(T);
        //} //eof method


        //public bool SearchFieldByValue(object obj, string strFieldName, object objFieldValue)
        //{
        //  //old configure the logger
        //  logger.Debug("METHOD START --- SearchFieldByValue");



        //  FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.NonPublic| BindingFlags.Instance| BindingFlags.FlattenHierarchy);

        //  foreach (FieldInfo field in fields)
        //  {
        //    object objFieldValueReflected = field.GetValue(obj);
        //    logger.Debug(field.Name + " = " + field.GetValue(obj));
        //    if (objFieldValueReflected != null && objFieldValue.ToString().Equals(objFieldValueReflected.ToString()))
        //      return true;
        //    else
        //      continue;
        //  }
        //  return false;

        //} //eof method 


        //public bool SearchPropByValue(object obj, string strFieldName, object objPropValue)
        //{
        //  if (obj == null)
        //    return false; 


        //  PropertyInfo[] props = obj.GetType().GetProperties(BindingFlags.Public);


        //  foreach (PropertyInfo prop in props)
        //  {
        //    if (prop != null)
        //    {
        //      object objpropaValueReflected = prop.GetValue(obj, null);

        //      System.Diagnostics.Debug.WriteLine(prop.Name + " = " + prop.GetValue(obj, null));
        //      if (objpropaValueReflected != null && objPropValue.ToString().Equals(objpropaValueReflected.ToString()))
        //        return true;
        //      else
        //        continue;
        //    }
        //    else
        //      continue; 
        //  }
        //  return false;

        //} //eof method 

        #endregion MethodsInDev

    } //eof class 	

} //eof namespace



//namespace TestPool
//{
//  class Program
//  {
//    private static readonly ILog logger =
//LogManager.GetLogger ( typeof ( Program ) ); //create the logging object 

//    public static DH.ObjectPool pool = new DH.ObjectPool ();

//    static void Main ( string[] args )
//    {
//      DOMConfigurator.Configure (); //tis configures the logger 

//      #region CreateTheBusinessObjects
//      Animal dog = new Animal () { Name = "Fido", ID = 1 };
//      Vegetable carrot = new Vegetable { Color = "Orange", Identifier = 2, IsTasty = true };
//      Mineral carbon = new Mineral () { UniqueID = 3, IsPoisonousToAnimal = false, Name = "some" };
//      HolderForStrings hfs = new HolderForStrings () { ID = 4, Value = "user_name", MetaName = "meta_nam" };
//      HolderForStrings hfs1 = new HolderForStrings () { ID = 5, Value = "user_name", MetaName = "hfs1" };
//      Mineral carbon1 = new Mineral () { UniqueID = 3, IsPoisonousToAnimal = false, Name = "some1" };
//      #endregion CreateTheBusinessObjects

//      #region AddTheBOToThePool
//      pool..AddItem ( dog );
//      pool..AddItem ( carrot );
//      pool..AddItem ( hfs );
//      pool..AddItem ( hfs1 );
//      #endregion AddTheBOToThePool

//      #region UncommentForMoreTesting
//      //pool..AddItem<Animal>(dog.ID, dog);
//      //pool..AddItem<Vegetable>(carrot.Identifier, carrot);
//      //pool..AddItem<Mineral> ( carbon );
//      //pool..AddItem<HolderForStrings> ( 1, hfs );

//      //logger.Info("Dog is in the pool -- this statement is " + pool.ContainsKey<Animal>(dog.ID));
//      //logger.Info("hfs is in the pool -- this statement is " + pool.ContainsKey<HolderForStrings>(hfs.ID));
//      //logger.Info("The hfs value is from the poos is " + pool.GetItem<HolderForStrings>(4).Value);

//      //logger.Info("poo.GetItems is " + pool.GetItems<HolderForStrings>());

//      #endregion UncommentForMoreTesting


//      #region while
//      //for (int i = 0; i < pool.Count -1 ; i++)
//      int i = 1;
//      do
//      {
//        try
//        {
//          logger.Info ( "counting" );
//          logger.Info ( " i is " + i.ToString () );
//          if (pool.ContainsKey<Animal> ( i ))
//          {
//            logger.Info ( " I see animal which is " + pool.GetItem<Animal> ( i ).Name );
//          }

//          if (pool.ContainsKey<Vegetable> ( i ))
//          {
//            logger.Info ( " I see Vegetable which is " + pool.GetItem<Vegetable> ( i ).Color );
//          }


//          if (pool.ContainsKey<Mineral> ( i ))
//          {
//            logger.Info ( " I see Mineral which is " + pool.GetItem<Mineral> ( i ).IsPoisonousToAnimal );
//          }


//          if (pool.ContainsKey<HolderForStrings> ( i ))
//          {
//            logger.Info ( " I see string which is " + pool.GetItem<HolderForStrings> ( i ).Value );
//          }

//          //logger.Info("pool.GetItem<HolderForStrings>(4).Value); is " + pool.GetItem<Object>(i).ToString());

//          i = i + 1;
//        }
//        catch (KeyNotFoundException e)
//        {
//          continue;
//        }

//      } //eof for 
//      while (i < pool.TotalCount);
//      #endregion while

//      #region AddHolders
//      ////this is the success identifier
//      //HoldInt16 holdVerifier = new HoldInt16()
//      //{
//      //  ID=0 ,
//      //  MetaName = "ret",
//      //  Value = 0
//      //};
//      //pool..AddItem<HoldInt16>(holdVerifier.ID, holdVerifier);

//      //ListDictionary lidMetaName = pool.LidMetaName;
//      ////this is the message
//      //HoldString holdMsg = new HoldString( ref lidMetaName)
//      //{
//      //  ID=1,
//      //  MetaName = "msg",
//      //  Value = msg,
//      //  Title = "title" 
//      //};
//      //pool..AddItem<HoldString>(holdMsg.ID, holdMsg);


//      //HoldString holdmmsg = new HoldString(ref lidMetaName)
//      //{
//      //  ID=2,
//      //  MetaName = "mmsg",
//      //  Value = "mmsg" , 
//      //  Title = "title" 
//      //};
//      #endregion AddHolders

//      //Utils.Debugger.DebugListDictionary(ref msg, "domainName", ref lidMetaName);
//      //get the value be metaName

//      logger.Info ( "I queried the pool by property with meta Value and value user_name " );

//      HolderForStrings HolderForStrings = pool.GetItemByPropertyValue<HolderForStrings> ( "MetaName", "hfs1" );
//      //logger.Info ( "object dump" + Utils.Log.ObjDumper.DumpObject ( HolderForStrings ) );
//      logger.Info ( "I found the following value for property with the name \"Name\" " );
//      logger.Info ( HolderForStrings.MetaName );

//      Console.ReadLine ();
//    } //eof Main

//  } //eof class 

//  #region ExampleBusinessObjects
//  public class Animal
//  {
//    public Int32 ID { get; set; }
//    public String Name { get; set; }
//  }

//  public class HolderForStrings
//  {
//    public Int32 ID { get; set; }
//    public String Value { get; set; }
//    public String MetaName { get; set; }
//    Type ObjType = typeof ( string );
//    public Int32 Size { get; set; }
//    public bool IsOptional { get; set; }
//    public bool IsPrimaryKey { get; set; }

//  } //eof class


//  public class Vegetable
//  {
//    public Int32 Identifier { get; set; }
//    public String Color { get; set; }
//    public Boolean IsTasty { get; set; }
//  }

//  public class Mineral
//  {
//    public Int32 UniqueID { get; set; }
//    public Boolean IsPoisonousToAnimal { get; set; }
//    public String Name { get; set; }
//  }

//  #endregion ExampleOfBusinessObjects
//} //eof class 
